clc;
clear all;
close all;

%% Initial
fprintf('SIMULATOR\n');
N = [4, 8, 12];
lower = 0.0;
upper = 0.9999999999999999;
q = 0.8;


arr_mae_rn = cell(1, length(N));
arr_mae_zr = cell(1, length(N));
arr_mae_cc = cell(1, length(N));
arr_mae_vr = cell(1, length(N));
arr_mae_hb = cell(1, length(N));

arr_ab_rn = cell(1, length(N));
arr_ab_zr = cell(1, length(N));
arr_ab_cc = cell(1, length(N));
arr_ab_vr = cell(1, length(N));
arr_ab_hb = cell(1, length(N));

for i = 1:length(N)
    fprintf('--------------------------------------------------------------\n');
    fprintf('N = %d\n', N(i));
    
    n = N(i);
    r = n;
    K = 0:(floor(n/4.0) + 2);
    
    step = 2^(-n);
    num = (round((upper-lower)/step) + 1);
    ab_rn_k = zeros(length(K), 2);
    ab_zr_k = zeros(length(K), 2);
    ab_cc_k = zeros(length(K), 2);
    ab_vr_k = zeros(length(K), 2);
    ab_hb_k = zeros(length(K), 2);
    
    max_rn_k = zeros(length(K));
    max_zr_k = zeros(length(K));
    max_cc_k = zeros(length(K));
    max_vr_k = zeros(length(K));
    max_hb_k = zeros(length(K));
    
    for j = 1:length(K)
        fprintf('\t k = %d\n', K(j));
        k = K(j);
        
        
        ab_rn = zeros(1, 2);
        ab_zr = zeros(1, 2);
        ab_cc = zeros(1, 2);
        ab_vr = zeros(1, 2);
        ab_hb = zeros(1, 2);
        
        max_rn = 0.0;
        max_zr = 0.0;
        max_cc = 0.0;
        max_vr = 0.0;
        max_hb = 0.0;
        
        index = 0;
        for a = lower:step:upper
            tStart = tic;
            index = index + 1;
            for b = a:step:upper
                
                ans_true = a * b;
                
                ans_true_r = rnd_near(ans_true, n);
                err_true = abs(ans_true - ans_true_r);
                if (err_true > max_rn)
                    max_rn = err_true;
                    ab_rn = [a, b];
                end
                ans_zr = trunc_mult(a, b, 0.0, n, n, r, k);
                err_zr = abs(ans_zr - ans_true);
                if (err_zr > max_zr)
                    max_zr = err_zr;
                    ab_zr = [a, b];
                end                                
                
                ans_cc = ccm(a, b, n, n, r, k);
                err_cc = abs(ans_cc - ans_true);
                if(err_cc > max_cc)
                    max_cc = err_cc;
                    ab_cc = [a, b];
                end
                ans_vr = vcm(a, b, n, n, r, k);
                err_vr = abs(ans_vr - ans_true);
                if(err_vr > max_vr)
                    max_vr = err_vr;
                    ab_vr = [a, b];
                end
                ans_hb = hcm(a, b, n, n, r, k, 0.5);
                err_hb = abs(ans_hb - ans_true);
                if(err_hb > max_hb)
                    max_hb = err_hb;
                    ab_hb = [a, b];
                end                                                                           
            end
            tLoop = toc(tStart);   
            percent = double(index/num) * 100;
            tLeft = tLoop * (num - index);
            fprintf('\t\tN = %d - k = %d - Index = %d - Num = %d - Percent: %f - Time: %s - Left: %f hrs\n',n,k,index, num, percent, datestr(datenum(0,0,0,0,0,tLoop),'HH:MM:SS'),tLeft/3600.0 );
        end
        max_rn_k(j) = max_rn;
        max_zr_k(j) = max_zr;
        max_cc_k(j) = max_cc;
        max_vr_k(j) = max_vr;
        max_hb_k(j) = max_hb;
        
        ab_rn_k(j,:) = ab_rn;
        ab_zr_k(j,:) = ab_zr;
        ab_cc_k(j,:) = ab_cc;
        ab_vr_k(j,:) = ab_vr;
        ab_hb_k(j,:) = ab_hb;
        
    end
    arr_mae_rn{i} = max_rn_k;
    arr_mae_zr{i} = max_zr_k;
    arr_mae_cc{i} = max_cc_k;
    arr_mae_vr{i} = max_vr_k;
    arr_mae_hb{i} = max_hb_k;
    
    arr_ab_rn{i} = ab_rn_k;
    arr_ab_zr{i} = ab_zr_k;
    arr_ab_cc{i} = ab_cc_k;
    arr_ab_vr{i} = ab_vr_k;
    arr_ab_hb{i} = ab_hb_k;
    
end
fprintf('\n');

%% Print out result
filename = 'result_max_abs_err_';
config = mat2str(N);
stamp = datestr(now);
%rand_num = num2str(randi(1000,1,1));
filename = strcat(filename, config,'_', stamp,'.txt');
fid = fopen(filename, 'w');
fprintf(fid,'Printing result...\n');
for i = 1:length(N)
    fprintf(fid,'N = %d \n', N(i));
    max_rn_k = arr_mae_rn{i};
    max_zr_k = arr_mae_zr{i};
    max_cc_k = arr_mae_cc{i};
    max_vr_k = arr_mae_vr{i};
    max_hb_k = arr_mae_hb{i};
    
    ab_rn_k = arr_ab_rn{i};
    ab_zr_k = arr_ab_zr{i};
    ab_cc_k = arr_ab_cc{i};
    ab_vr_k = arr_ab_vr{i};
    ab_hb_k = arr_ab_hb{i};
    
    K = 0:(floor(N(i)/4.0) + 2);
    for j = 1:length(K)
        max_rn = max_rn_k(j);
        max_zr = max_zr_k(j);
        max_cc = max_cc_k(j);
        max_vr = max_vr_k(j);
        max_hb = max_hb_k(j);
        
        ab_rn = ab_rn_k(j,:);
        ab_zr = ab_zr_k(j,:);
        ab_cc = ab_cc_k(j,:);
        ab_vr = ab_vr_k(j,:);
        ab_hb = ab_hb_k(j,:);
        fprintf(fid,'\t k = %d - ulp = %f - correct unit = %f \n', K(j), 2^(-N(i)), 2^(-N(i)-K(j)));
        
        fprintf(fid,'\t\t Rounding: Max = %f - ',max_rn);
        fprintf(fid,'A = '); 
        disp_bin(ab_rn(1), 0, N(i), fid);
        fprintf(fid,'- B = ');
        disp_bin(ab_rn(2), 0, N(i), fid);
        fprintf(fid, '\n');
        
        fprintf(fid,'\t\t Truncation: Max = %f - ',max_zr);
        fprintf(fid,'A = '); 
        disp_bin(ab_zr(1), 0, N(i), fid);
        fprintf(fid,'- B = ');
        disp_bin(ab_zr(2), 0, N(i), fid);
        fprintf(fid, '\n');
        
        fprintf(fid,'\t\t CCT: Max = %f - ',max_cc);
        fprintf(fid,'A = '); 
        disp_bin(ab_cc(1), 0, N(i), fid);
        fprintf(fid,'- B = ');
        disp_bin(ab_cc(2), 0, N(i), fid);
        fprintf(fid, '\n');
        
        fprintf(fid,'\t\t VCT: Max = %f - ',max_vr);
        fprintf(fid,'A = '); 
        disp_bin(ab_vr(1), 0, N(i), fid);
        fprintf(fid,'- B = ');
        disp_bin(ab_vr(2), 0, N(i), fid);
        fprintf(fid, '\n');
        
        fprintf(fid,'\t\t HCT: Max = %f - ',max_hb);
        fprintf(fid,'A = '); 
        disp_bin(ab_hb(1), 0, N(i), fid);
        fprintf(fid,'- B = ');
        disp_bin(ab_hb(2), 0, N(i), fid);
        fprintf(fid, '\n');
    end
end

